<?php


namespace App\Crontab;


use App\Model\CacheTable;
use App\Model\DataTable;
use App\Model\Pay\Transfer;
use App\Model\User;
use App\Model\Wechat;
use App\Utility\Pool\MysqlPool;
use App\Utility\Queue\Queue;
use App\Utility\Queue\QueueType;
use EasySwoole\EasySwoole\Crontab\AbstractCronTask;
use EasySwoole\EasySwoole\Task\TaskManager;
use EasySwoole\Pay\Exceptions\GatewayException;
use EasySwoole\Pay\Exceptions\InvalidSignException;
use EasySwoole\Pay\Utility\NewWork;
use EasySwoole\Pay\WeChat\Config;
use EasySwoole\Pay\WeChat\RequestBean\Base;
use EasySwoole\Pay\WeChat\Utility;
use EasySwoole\Queue\Job;
use EasySwoole\Spl\SplArray;
use EasySwoole\WeChat\Bean\OfficialAccount\TemplateMsg;

class OrderTask extends AbstractCronTask
{

    private static $ORDER_FILDE = 'id,user_id,order_no,paymount';


    public static function getRule(): string
    {
        // TODO: Implement getRule() method.
        //return '0 */8 * * *';
        return '*/5 * * * *';
    }

    public static function getTaskName(): string
    {
        // TODO: Implement getTaskName() method.
        return 'OrderTask';
    }


    function run(int $taskId, int $workerIndex)
    {
        // TODO: Implement run() method.
        //echo('send'.self::getTaskName().PHP_EOL);
        TaskManager::getInstance()->async(function () {
            OrderTask::SetPage('已提交', QueueType::MESSAGE_SUMBIT_ORDER);
            //再发送已审核的
            OrderTask::SetPage('已审核', QueueType::MESSAGE_VERIFY_ORDER);
        });

    }

    function onException(\Throwable $throwable, int $taskId, int $workerIndex)
    {
        // TODO: Implement onException() method.
        echo $throwable->getMessage();
    }


    public static function SetPage($status, $msg)
    {
        // TODO: Implement run() method.
        //查询所有出来
        $db = MysqlPool::defer();
        //发工作
        $page_size = 100;
        $count = $db->where('status', $status, '=')->count(DataTable::ORDER_TABLE);
        $pages = (int)$count / $page_size;
        if ($pages < 1) {
            $list = $db->where('status', $status, '=')->get(DataTable::ORDER_TABLE, null, self::$ORDER_FILDE);
            //添加一个JOB哦
            self::SetJob($list, $msg);
        } else {
            for ($page = 0; $page < $pages - 1; $page++) {
                $list = $db->where('status', $status, '=')->get(DataTable::ORDER_TABLE, [$page * $page_size, $page_size], self::$ORDER_FILDE);
                //添加一个JOB
                self::SetJob($list, $msg);
            }
            //取余数
            $mod = $count % $page_size;
            if ($mod > 0) {
                $list = $db->where('status', $status, '=')->get(DataTable::ORDER_TABLE, [$count - $mod, $mod], self::$ORDER_FILDE);
                self::SetJob($list, $msg);
            }
        }
    }

    private static function SetJob($list, $type)
    {
        if (count($list) > 0) {
            $job = new Job();
            $data['list'] = $list;
            $data['type'] = $type;
            $job->setJobData($data);
            Queue::getInstance()->producer()->push($job);
        }
    }

    public static function consumer_sumbit($list)
    {
        $db = MysqlPool::defer();
        foreach ($list as $order) {
            try {
                $orderobj['status'] = '待审核';
                $orderobj['updatetime'] = time();
                $money_arr = [100, 500];
                if (in_array($order['paymount'], $money_arr)) {
                    $isDeny = User::isDeny($order['user_id']);
                    if ($isDeny) {
                        break;
                    }
                    //取记录
                    $list = $db->where('user_id', $order['user_id'], '=')
                        ->orderBy('id')
                        ->get(DataTable::SCORE_LOG_TABLE);

                    if (is_array($list)) {
                        $after = $list[0]['after'];
                        $before = $list[count($list) - 1]['before'];
                        $falg = true;
                        $total = 0;
                        foreach ($list as $item) {
                            if ($item['after'] - $item['before'] != $item['score']) {
                                $falg = false;
                                break;
                            }
                            $total += $item['score'];
                        }

                        if ($after - $before != $total) {
                            $falg = false;
                        }
                        if ($falg) {
                            $info = $db->where('id', $order['user_id'], '=')
                                ->getOne(DataTable::USER_TABLE, 'score,freeze_score');
                            //判断账号冰结金币是否等于提现金币
                            if (array_key_exists('freeze_score', $info)) {
                                //判断是否对
                                if ($info['freeze_score'] == $order['paymount'] && $info['score'] == $after) {
                                    $orderobj['status'] = '已审核';
                                }
                            }
                        }
                    }
                }
                //更新状态
                $db->where('id', $order['id'], '=')
                    ->update(DataTable::ORDER_TABLE, $orderobj);
            } catch (\Exception $e) {
                continue;
            }
        }


    }

    public static function consumer_verify($list)
    {
        $config = \EasySwoole\EasySwoole\Config::getInstance()->getConf('WECHAT.pay');
        //更新状态
        $wechatConfig = new Config();
        $wechatConfig->setAppId($config['appId']);      // 除了小程序以外使用该APPID
        $wechatConfig->setMchId($config['mchId']);
        $wechatConfig->setKey($config['key']);
        $wechatConfig->setNotifyUrl($config['notifyUrl']);
        $wechatConfig->setApiClientCert(EASYSWOOLE_ROOT . $config['apiClientCert']);//客户端证书
        $wechatConfig->setApiClientKey(EASYSWOOLE_ROOT . $config['apiClientKey']); //客户端证书秘钥
        self::redpack($list, $wechatConfig);
    }

    //微信红包接口
    private static function redpack($list, $wechatConfig)
    {
        $db = MysqlPool::defer();
        foreach ($list as $order) {

            $orderupdater['updatetime'] = time();
            $orderupdater['status'] = '发放失败';
            $isDeny = User::isDeny($order['user_id']);
            if (!$isDeny) {
                //用户信息
                $userinfo = $db->where('id', $order['user_id'], '=')
                    ->getOne(DataTable::USER_TABLE, 'freeze_score');
                //查询openid
                $thrid = $db->where('user_id', $order['user_id'], '=')
                    ->getOne(DataTable::THIRD_TABLE, 'openid');
                try {
                    if (array_key_exists('freeze_score', $userinfo) && array_key_exists('openid', $thrid)) {
                        if ($userinfo['freeze_score'] == $order['paymount']) {
                            //清空冻结
                            $userupdatainfo['freeze_score'] = 0;
                            $db->where('id', $order['user_id'], '=')->update(DataTable::USER_TABLE, $userupdatainfo);
                            //发起红包
                            $redpack = new \App\Model\Pay\RedPack();
                            $redpack->setMchBillno($order['order_no']);
                            $redpack->setMchId($wechatConfig->getMchId());
                            $redpack->setWxappid($wechatConfig->getAppid());
                            $redpack->setSendName('上证先知道');
                            $redpack->setReOpenid($thrid['openid']);
                            $redpack->setTotalAmount($order['paymount']);
                            $redpack->setTotalNum(1);
                            $redpack->setWishing('这是你兑换的' . ($order['paymount'] / 100) . '元红包，请注意查收');
                            $redpack->setClientIp(swoole_get_local_ip()['eth0']);
                            $redpack->setActName('竞猜积分兑换红包');
                            $redpack->setRemark('竞猜积分兑换红包');
                            $params = self::pay($wechatConfig, '/mmpaymkttransfers/sendredpack', $redpack, true);
                            if (array_key_exists('result_code', $params) && $params['result_code'] == 'SUCCESS') {
                                //判断支付的金额对不
                                if ($params['total_amount'] == $order['paymount'] && $params['re_openid'] == $thrid['openid'] && $params['mch_billno'] == $order['order_no']) {
                                    $orderupdater['err_dec'] = 'SUCCESS';
                                    $orderupdater['status'] = '已发放';
                                } else {
                                    $orderupdater['status'] = '系统异常';
                                    $orderupdater['err_dec'] = '脏数据？' . $params['mch_billno'] . '::' . $params['total_amount'] . '::' . $params['re_openid'];
                                }
                                $orderupdater['send_listid'] = $params['send_listid'];

                            } else if (array_key_exists('result_code', $params) && $params['result_code'] == 'FAIL') {
                                $orderupdater['status'] = '待发放';
                                //失败
                                $orderupdater['err_dec'] = $params['err_code'] . ':' . $params['err_code_des'];
                            }
                        }
                    }
                } catch (\Exception $e) {
                    $db->where('id', $order['user_id'])
                        ->update(DataTable::ORDER_TABLE, $orderupdater);
                    //发消息给用户
                    self::sendPayFailMsg($thrid);
                    continue;
                }
            }
            $db->where('id', $order['id'], '=')
                ->update(DataTable::ORDER_TABLE, $orderupdater);


        }
    }

    private static function transfer($list, $wechatConfig)
    {
        $db = MysqlPool::defer();
        foreach ($list as $order) {
            try {
                //用户信息
                $userinfo = $db->where('id', $order['user_id'], '=')
                    ->getOne(DataTable::USER_TABLE, 'freeze_score');
                //查询openid
                $thrid = $db->where('user_id', $order['user_id'], '=')
                    ->getOne(DataTable::THIRD_TABLE, 'openid');
                $orderupdater['updatetime'] = time();
                $orderupdater['status'] = '发放失败';
                if (array_key_exists('freeze_score', $userinfo) && array_key_exists('openid', $thrid)) {
                    if ($userinfo['freeze_score'] == $order['paymount']) {
                        //清空冻结
                        $userupdatainfo['freeze_score'] = 0;
                        $db->where('id', $order['user_id'], '=')->update(DataTable::USER_TABLE, $userupdatainfo);
                        //发起红包
                        $transfer = new Transfer();
                        $transfer->setPartnerTradeNo($order['order_no']);
                        $transfer->setOpenid($thrid['openid']);
                        $transfer->setCheckName('NO_CHECK');
                        $transfer->setAmount($order['paymount']);
                        $transfer->setDesc('竞猜大盘涨跌积分兑换红包活动');
                        $transfer->setMchAppid($wechatConfig->getAppId());
                        $transfer->setMchid($wechatConfig->getMchId());
                        $transfer->setSpbillCreateIp(swoole_get_local_ip()['eth0']);
                        $params = self::pay($wechatConfig, '/mmpaymkttransfers/promotion/transfers', $transfer, true);
                        if (array_key_exists('result_code', $params) && $params['result_code'] == 'SUCCESS') {

                            //判断支付的金额对不
                            if ($params['partner_trade_no'] == $order['order_no']) {
                                $orderupdater['err_dec'] = 'SUCCESS' . ':' . $params['payment_time'];
                                $orderupdater['status'] = '已发放';
                            } else {
                                $orderupdater['status'] = '系统异常';
                                $orderupdater['err_dec'] = '脏数据？' . $params['partner_trade_no'] . '::' . $params['payment_no'] . '::' . $params['payment_time'];
                            }
                            $orderupdater['send_listid'] = $params['payment_no'];

                        } else if (array_key_exists('result_code', $params) && $params['result_code'] == 'FAIL') {
                            $orderupdater['status'] = '待发放';
                            //失败
                            $orderupdater['err_dec'] = $params['err_code'] . ':' . $params['err_code_des'];
                        }
                    }
                }
                $db->where('id', $order['id'], '=')
                    ->update(DataTable::ORDER_TABLE, $orderupdater);
            } catch (\Exception $e) {
                continue;
            }

        }
    }

    private static function pay($wechatConfig, string $endpoint, Base $bean, bool $useCert = false): SplArray
    {
        $util = new Utility($wechatConfig);
        $bean->setSign($util->generateSign($bean->toArray()));
        $response = NewWork::postXML($wechatConfig->getGateWay() . $endpoint, (new SplArray($bean->toArray()))->toXML(), $useCert ? [
            'ssl_cert_file' => $wechatConfig->getApiClientCert(),
            'ssl_key_file' => $wechatConfig->getApiClientKey()]
            : []);
        if ($response->getStatusCode() == 200) {
            $result = $response->getBody();
            $result = is_array($result) ? $result : $util->fromXML($result);

            if (!isset($result['return_code']) || $result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS') {
                throw new GatewayException('Get Wechat API Error:' . ($result['return_msg'] ?? $result['retmsg']) . ($result['err_code_des'] ?? ''), 20000);
            }
            if (strpos($endpoint, 'mmpaymkttransfers') !== false || $util->generateSign($result) === $result['sign']) {
                return new SplArray($result);
            }
            throw new InvalidSignException('sign is error');
        }
        throw new GatewayException('Get Wechat API Error url:' . $wechatConfig->getGateWay() . $endpoint . ' params:' . $bean->__toString(), 20000);
    }


    public static function sendPayFailMsg($msg)
    {
        $wechat = new Wechat();
        $client = $wechat->GetClient();
        $date_str = date("Y/m/d");
        $data['first']['value'] = '尊敬的' . $msg['openname'] . '，很抱歉,提现失败';
        $data['keyword1']['value'] = $date_str;
        $data['keyword2']['value'] = '你的账号因支付权限不足，不能完成提现，请完成实名认证';
        $data['remark']['value'] = '如有问题可私信留言，联系客服。';
        $tempmsg = new TemplateMsg();
        $tempmsg->setTemplateId('6x4SL-c-cEjt4RW4rcTRuo1DmN67X0nnVGA15O8eA1k');
        $tempmsg->setTouser($msg['openid']);
        $tempmsg->setData($data);
        $tempmsg->setUrl(CacheTable::getFinanceConfig()['PAY_URL']);
        try {
            $client->officialAccount()->templateMsg()->send($tempmsg);
        } catch (\Exception $e) {
            var_dump($e->getMessage());
        }
    }


}